package me.zhengjie.utils;

import me.zhengjie.exception.BadRequestException;
import me.zhengjie.utils.enums.BusinessType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Component
public class SerialNumberUtil {

    @Autowired
    private StringRedisTemplate redisTemplate;

    // 设置 Redis 键的过期时间（24小时）
    private static final int EXPIRE_TIME_SECONDS = 24 * 60 * 60;

    /**
     * 单个流水号生成
     *
     * @param businessType 枚举业务类型
     * @return 生成的流水号
     */
    public String generateSerialNumber(String businessType) {
        return generateBatchSerialNumbers(businessType, 1).get(0);
    }

    /**
     * 批量流水号生成
     *
     * @param type 枚举业务类型
     * @param batchSize    流水号数量
     * @return 流水号列表
     */
    public List<String> generateBatchSerialNumbers(String type, int batchSize) {
        BusinessType businessType = validateBusinessType(type);
        // 当前日期
        String dateStr = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        // 根据业务类型获取前缀
        String prefix = businessType.getPrefix();
        // Redis 键：业务类型 + 日期
        String redisKey = prefix + ":serial:" + dateStr;

        // 流水号列表
        List<String> serialNumbers = new ArrayList<>();

        for (int i = 0; i < batchSize; i++) {
            // 自增流水号
            Long sequence = redisTemplate.opsForValue().increment(redisKey);

            // 如果是第一次生成，设置过期时间
            if (sequence != null && sequence == 1) {
                redisTemplate.expire(redisKey, EXPIRE_TIME_SECONDS, TimeUnit.SECONDS);
            }

            // 格式化流水号为 4 位补零
            String formattedSequence = String.format("%04d", sequence);

            // 拼接完整流水号
            serialNumbers.add(prefix + dateStr + formattedSequence);
        }

        return serialNumbers;
    }

    /**
     * 校验并转换业务类型
     *
     * @param type 请求中的业务类型
     * @return 对应的枚举值
     * @throws BadRequestException 如果类型不合法
     */
    private BusinessType validateBusinessType(String type) {
        try {
            return BusinessType.valueOf(type.toUpperCase());
        } catch (IllegalArgumentException e) {
            throw new BadRequestException("传入的类型不合法: " + type);
        }
    }
}